package com.onpositive.page.pagerendering;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.HashMap;
import java.util.LinkedHashMap;

import javax.servlet.ServletContext;
import javax.servlet.ServletResponse;

import com.onpositive.page.pagerendering.interfaces.ISiteContentRenderer;

import com.onpositive.storage.managers.AccountManager;
import com.onpositive.storage.managers.UnifiedContentProvider;

import freemarker.cache.WebappTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class SiteContentRenderer implements ISiteContentRenderer {

	private static SiteContentRenderer renderer;

	public static final String MENU_RESOURCE = "/menu.conf";
	public static final String TEMPLATE_RESOURCE = "/template.html";
	public static final String CSS_RESOURCE ="/res/initial.css";

	private MenuRenderer menu;
	private Template temp;

	private SiteContentRenderer() {

	}

	public static ISiteContentRenderer getSiteContentRenderer() {
		if (renderer == null) {
			renderer = new SiteContentRenderer();
		}
		return renderer;
	}

	@SuppressWarnings("unchecked")
	public void render(ServletResponse arg1, Reader wikiContent, String url,
			boolean enableEditing) {

		HashMap rootMap = new HashMap();

		AccountsManagementRenderer login = new AccountsManagementRenderer(url,
				AccountManager.getCurrentUserNickName());
		boolean isLoginned = AccountManager.isUserLoginned();
		EditLinkRenderer edlr = new EditLinkRenderer(url);

		LinkedHashMap<String, String> addition = new LinkedHashMap<String, String>();
		String renderContent = WikiRendererImpl.renderContent(wikiContent,
				addition);

		rootMap.put("menu", menu.menu(url, isLoginned));

		if (enableEditing) {
			rootMap.put("edit", edlr.getEditLink());
		} else {
			rootMap.put("edit", "");
		}

		rootMap.put("content", renderContent);
		String e1 = (String) addition.get("extras");
		if (e1 == null) {
			e1 = "";
		}
		String extras = (String) addition.get("subcontent");
		if (extras == null) {
			extras = "";
		}
		rootMap.put("extras", e1);
		rootMap.put("subcontent", extras);
		String loginLink = login.getLoginLink();
		rootMap.put("login", loginLink);

		PrintWriter writer;
		try {
			writer = arg1.getWriter();
			temp.process(rootMap, writer);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateException e) {
			e.printStackTrace();
		}

	}

	@SuppressWarnings("unchecked")
	public void render(ServletResponse arg1, String wikiContent, String url,
			boolean editableContent, boolean useHighlighting) {

		HashMap rootMap = new HashMap();

		AccountsManagementRenderer login = new AccountsManagementRenderer(url,
				AccountManager.getCurrentUserNickName());
		EditLinkRenderer edlr = new EditLinkRenderer(url);
		boolean isLoginned = AccountManager.isUserLoginned();

		LinkedHashMap<String, String> addition = new LinkedHashMap<String, String>();
		String renderContent = wikiContent;

		rootMap.put("menu", menu.menu(url, isLoginned));
		if (editableContent) {
			rootMap.put("edit", edlr.getEditLink());
		} else {
			rootMap.put("edit", "");
		}

		rootMap.put("content", renderContent);
		String e1 = (String) addition.get("extras");
		if (e1 == null) {
			e1 = "";
		}
		if (useHighlighting) {
			String importHighlighting = "<script src=\"/codemirror/js/codemirror.js\" type=\"text/javascript\"></script>\r\n"
					+ "<style type=\"text/css\">\r\n"
					+ ".CodeMirror-line-numbers {\r\n"
					+ "width: 2.2em;\r\n"
					+ "color: #aaa;\r\n"
					+ "background-color: #eee;\r\n"
					+ "text-align: right;\r\n"
					+ "padding-right: .3em;\r\n font-size: 10pt;\r\n font-size: 10pt;\r\n font-family: monospace;\r\n padding-top: .4em;\r\n }\r\n"
					+ ".CodeMirror-wrapping {\r\n border-style: solid;\r\n border-color: #dddddd;\r\n border-widht: 1px;\r\n }\r\n + </style>\r\n";
			e1 += "\r\n" + importHighlighting;
		}

		String extras = (String) addition.get("subcontent");
		if (extras == null) {
			extras = "";
		}
		rootMap.put("extras", e1);
		rootMap.put("subcontent", extras);
		String loginLink = login.getLoginLink();
		rootMap.put("login", loginLink);

		PrintWriter writer;
		try {
			writer = arg1.getWriter();
			temp.process(rootMap, writer);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateException e) {
			e.printStackTrace();
		}

	}

	public void initRenderer(ServletContext servletContext) {
		ServletContext context = servletContext;
		Configuration t = new Configuration();
		t.clearTemplateCache();

		if (!UnifiedContentProvider.isContainContentElement(TEMPLATE_RESOURCE)) {
			UnifiedContentProvider.storeContentElement(TEMPLATE_RESOURCE,
					InitContentRenderer.getInitialPageTemplate());
			UnifiedContentProvider.storeContentElement(CSS_RESOURCE,
					InitContentRenderer.getInitialStyleContent());
		}

		if (!UnifiedContentProvider.isContainContentElement(MENU_RESOURCE)) {
			UnifiedContentProvider.storeContentElement(MENU_RESOURCE,
					InitContentRenderer.getInitialMenu());
		}

		if (t == null || true) {
			t.setTemplateLoader(new WebappTemplateLoader(servletContext));
			t.setObjectWrapper(new DefaultObjectWrapper());
			try {
				// UnifiedContentProvider.deleteContent(TEMPLATE_RESOURCE);
				// InputStream templateResourceAsStream =
				// context.getResourceAsStream(TEMPLATE_RESOURCE);
				// UnifiedContentProvider.storeContentElement(TEMPLATE_RESOURCE,
				// new InputStreamReader(templateResourceAsStream));
				InputStream tIs = UnifiedContentProvider
						.getContentElementAsStream(TEMPLATE_RESOURCE);
				temp = new Template(TEMPLATE_RESOURCE, new InputStreamReader(
						tIs), t);
				// t.getTemplate("/template.html");
				if (temp == null) {
					throw new IllegalStateException("Unable to load template");
				}
				// UnifiedContentProvider.deleteContentElement(MENU_RESOURCE);
				// InputStream menuResourceAsStream = context
				// .getResourceAsStream(MENU_RESOURCE);
				// UnifiedContentProvider.storeContentElement(MENU_RESOURCE,
				// new InputStreamReader(menuResourceAsStream));
				InputStream is = UnifiedContentProvider
						.getContentElementAsStream(MENU_RESOURCE);
				menu = new MenuRenderer(is);
				// menu = new MenuRenderer(menuResourceAsStream);

			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
